package service

import (
	"kingbloc.dts/models"
	"kingbloc.dts/tools"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

// 奖金
type Award struct {
}

func (a *Award) CalcAllAward() {
	//
	a.CalcAwardLayer()
	a.CalcAwardAmount()
	a.CalcAwardLucky()
	a.CalcAwardManagement()

	//

}

func (a *Award) CalcAwardCharm(account *model.Account) {

	myRecommendedOrders := MyRecommended(account.Id)
	length := len(myRecommendedOrders)
	if length < 5 {
		return
	}

	myOrders := new(model.Orderr).ByAccountId(account.Id)
	if len(myOrders) < 1 {
		return
	}
	myFirstOrder := myOrders[0]

	charmAward := model.NewCharmAward()
	charmAward.IncomeOrderId = myFirstOrder.Id
	charmAward.IntroducerIdsCount = length

	priceStr := strconv.FormatFloat(myFirstOrder.Price, 'f', 0, 64)
	if (length >= 5) && length <= 9 {
		charmAward.Price = tool.GetCharm5_9Price(priceStr)
	}
	if length >= 10 {
		charmAward.Price = tool.GetCharm5_9Price(priceStr)
	}
	charmAward.Add()

	// 记录魅力奖
	account.CharmAward = charmAward.Price
	account.UpdateCols("charm_award")

}

// 管理奖计算
func (a *Award) CalcAwardManagement() {

	// 收集数据
	las := new(model.ManagementAward).AllNotCalc()
	if len(las) == 0 {
		return
	}

	upLayerOrders := make(map[int]*model.Orderr)
	upIntroducerOrders := make(map[int]*model.Orderr)

	for _, v := range las {
		//
		incomeOrder := new(model.Orderr).ById(v.TriggerOrderId)

		GetOrdersForParentId(incomeOrder, incomeOrder.ParentId, upLayerOrders)
		GetOrdersForIntroducerId(1, incomeOrder, incomeOrder.ParentId, upIntroducerOrders)

		giveOutManageAward(upLayerOrders, v, incomeOrder, tool.GetUnitPrice(), tool.ManagementAwardRate)
		giveOutManageAward(upIntroducerOrders, v, incomeOrder, tool.GetUnitPrice(), tool.ManagementAwardRate)

		v.TriggerOrderIdBackup = v.TriggerOrderId
		v.TriggerOrderId = 0
		v.CalcTime = time.Now()
		v.Update()

	}

}

// 发放管理奖
func giveOutManageAward(orders map[int]*model.Orderr, v *model.ManagementAward, incomeOrder *model.Orderr, manageAwardXX1 map[string]int, managementAwardSate float64) {
	for k, v1 := range orders {
		if v.Id == incomeOrder.Id {
			continue
		}
		ref := strconv.FormatFloat(incomeOrder.Price, 'f', 0, 64)
		// 限制报单金额对应的层
		if k == manageAwardXX1[ref] {
			continue
		}

		sum := managementAwardSate * v.AmountPrice
		v1.AwardManagement = v1.AwardManagement + sum
		v1.UpdateManagementAward()
	}
}

// 幸运奖计算
// 量奖时增加的幸运奖数据
func (a *Award) CalcAwardLucky() {

	// 收集数据
	las := new(model.LuckyAward).AllNotCalc()
	//fmt.Println(las)
	if len(las) == 0 {
		return
	}

	for _, v := range las {

		selfOrder := new(model.Orderr).ById(v.TriggerOrderId)

		frontOrders := selfOrder.OrdersByBeforeTime(selfOrder.CreateAt, 20)

		back40OrdersRef := selfOrder.OrdersByAfterTime(selfOrder.CreateAt, 40)
		chaE := 20 - len(frontOrders)
		backOrders := make([]*model.Orderr, 20+chaE)

		if chaE > 0 {
			for k, v := range back40OrdersRef {

				if k == (20 + chaE) {
					break
				}
				backOrders[k] = v
			}
		}

		countOrders := make([]*model.Orderr, 40)
		for _, vv := range frontOrders {
			if vv == nil {
				continue
			}
			countOrders = append(countOrders, vv)
		}
		for _, vv2 := range backOrders {
			if vv2 == nil {
				continue
			}
			countOrders = append(countOrders, vv2)
		}

		// 量奖 * 幸运奖比例比例
		luckyAward := v.AmountPrice * tool.LuckyAwardRate

		for _, vv3 := range countOrders {
			if vv3 == nil {
				continue
			}
			// 幸运奖触发者自己不能给自己分配幸运奖
			if v.TriggerOrderId == vv3.Id {
				continue
			}
			vv3.AwardLucky = vv3.AwardLucky + luckyAward
			vv3.UpdateLuckyAward()
		}

		v.TriggerOrderIdBackup = v.TriggerOrderId
		v.TriggerOrderId = 0
		v.Update()

	}

}

// 量奖计算
func (a *Award) CalcAwardAmount() {

	// 收集数据整理
	_recordAmountAward()

	// 计算量奖
	aas := new(model.AmountAward).AllNotCalcAA()
	if len(aas) == 0 {
		return
	}

	// 当天所有的量碰奖
	var amountCount float64

	var count float64
	for _, v := range aas {

		//
		leftOrderIds := strings.Split(v.LeftAreaOrderIds, ",")
		rightOrderIds := strings.Split(v.RightAreaOrderIds, ",")

		if (len(leftOrderIds) == 0) || (len(rightOrderIds) == 0) {
			continue
		}

		leftCount := _SumForOrderIds(leftOrderIds)
		rightCount := _SumForOrderIds(rightOrderIds)
		count = leftCount + rightCount
		// 小区碰大区
		if leftCount < rightCount {
			count = leftCount
		} else {
			count = rightCount
		}
		v.LeftIdsBackup = v.LeftIdsBackup + "," + v.LeftAreaOrderIds
		v.RightIdsBackup = v.RightIdsBackup + "," + v.RightAreaOrderIds
		v.LeftAreaOrderIds = ""
		v.RightAreaOrderIds = ""
		v.LeftPrice = leftCount - count
		v.RightPrice = rightCount - count
		v.UpdateTime = time.Now()
		v.UpdateBack()

		result := count * tool.AmountAwardRate

		// 受益 order 的量奖更新
		incomeOrder := new(model.Orderr).ById(v.IncomeOrderId)
		incomeOrder.AwardAmount += result
		incomeOrder.UpdateAmountAward()

		// 记录幸运奖
		la := model.NewLuckyAward()
		la.TriggerOrderId = v.IncomeOrderId // 受益  order id
		la.AmountPrice = result
		la.Add()

		// 累积所有量碰奖
		amountCount += count

		// TODO： 发送异步通知

	}

	// 记录所有管理奖
	for _, v := range aas {

		//selfOrder := new(model.Orderr).ById(v.IncomeOrderId)
		ma := model.NewMangementAward()
		ma.TriggerOrderId = v.IncomeOrderId // 受益  order id
		ma.AmountPrice = amountCount
		ma.Add()

	}

}

func AmountAwardByOrderId(id int64) *model.AmountAward {
	return new(model.AmountAward).ByIncomeOrderId(id)
}

// 计算报单总价格
func _SumForOrderIds(orderIds []string) (result float64) {

	if len(orderIds) == 0 {
		return 0
	}

	order := new(model.Orderr)
	for _, v := range orderIds {
		if v == "" {
			continue
		}
		orderId, _ := strconv.ParseInt(v, 10, 64)
		order.ById(orderId)
		result += order.Price
	}

	return result
}

// 整理量奖谁
func _recordAmountAward() {
	todays := new(model.Today).All()

	recordLaLock := new(sync.Mutex)

	for _, v := range todays {
		recordLaLock.Lock()
		recordAmountAward(v)
		recordLaLock.Unlock()
		// v.Del() // 删除当前的新增单
	}
}

func recordAmountAward(today *model.Today) {

	// 触发 order
	newOrder := new(model.Orderr).ById(today.OrderId)
	// 受益orders
	orderBeneficiarys := make(map[int]*model.Orderr, 0)

	GetOrdersForParentId(newOrder, newOrder.ParentId, orderBeneficiarys)

	// 没有下级的 newOrder
	if len(orderBeneficiarys) == 0 {
		return
	}
	// 当前order layer 减去 受益order的layer, 就是受益order的第几层
	sortOrders := make([]int, len(orderBeneficiarys))
	i := 0
	for k, _ := range orderBeneficiarys {
		sortOrders[i] = k
		i++
	}

	sort.Ints(sortOrders)

	for iii, jjj := range sortOrders {

		incomeOrder := orderBeneficiarys[jjj] // 受益 order
		lastParentOrder := orderBeneficiarys[iii]

		refOrderChilds := incomeOrder.NextFloorOrdersByOrderId(incomeOrder.Id)

		if newOrder.Id == incomeOrder.Id {
			continue
		}
		// 同层的排序为1,2的不参与量碰
		//if newOrder.Sort <= 2 {
		//	return
		//}

		// 是否是层碰过的单
		hasLayerAwardOrder := new(model.LayerAward)
		if hasLayerAwardOrder.HasLayerAwardOrder(incomeOrder.Id, newOrder.Id) {
			continue
		}

		aa := new(model.AmountAward).FindByIncomeOrderId(incomeOrder.Id)
		leftAreaId := strconv.FormatInt(newOrder.Id, 10)
		// refOrderChilds 只有一个时,只可能添加层奖的左区 或 不添加
		if len(refOrderChilds) == 1 {
			childsIsOne(aa, lastParentOrder, incomeOrder, refOrderChilds, leftAreaId)
		} else {
			childIsTwo(aa, lastParentOrder, incomeOrder, refOrderChilds, leftAreaId)
		}
	}
}
func childIsTwo(aa *model.AmountAward, lastParentOrder *model.Orderr, incomeOrder *model.Orderr, refOrderChilds []*model.Orderr, leftAreaId string) {
	refOrderChildMin := refOrderChilds[0]
	refOrderChildMax := refOrderChilds[1]

	// 双轨制左右区每层的第一个单和第二个单相碰，产生层碰
	if lastParentOrder == nil {
		if aa == nil {
			maxId := strconv.FormatInt(refOrderChildMax.Id, 10)
			if maxId == leftAreaId {
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.RightAreaOrderIds = leftAreaId
				aa.Add()
			} else {
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.LeftAreaOrderIds = leftAreaId
				aa.Add()
			}
		} else {
			aa.RightAreaOrderIds += leftAreaId
		}
	} else {

		if aa == nil { // 存在两个下级，并且没有量奖记录，直接添加
			if refOrderChildMin.Id == lastParentOrder.Id { // 取chiild 0 一定是左区， 与 lastParentOrder ID 相等就是左区
				//model.NowAmountAward(incomeOrder.Id, leftAreaId).Add()
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.LeftAreaOrderIds = leftAreaId
				aa.Add()
			} else {
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.RightAreaOrderIds = leftAreaId
				aa.Add()
			}
		} else {

			// childs 按时间升序排列 0 是早起添加的，1 是后期添加的
			if refOrderChildMin.Id == lastParentOrder.Id { // 取chiild 0 一定是左区， 与 lastParentOrder ID 相等就是左区
				aa.UpdateLeftAreaIds(leftAreaId)
			} else {
				aa.UpdateRightAreaIds(leftAreaId)
			}
		}

	}
}
func childsIsOne(aa *model.AmountAward, lastParentOrder *model.Orderr, incomeOrder *model.Orderr, refOrderChilds []*model.Orderr, leftAreaId string) {
	if aa == nil {
		refOrderChildMin := refOrderChilds[0] // childs 按时间升序排列 0 是早起添加的，1 是后期添加的
		if lastParentOrder == nil {
			aa = model.NewAmountAward(incomeOrder.Id)
			aa.LeftAreaOrderIds = leftAreaId
			aa.Add()

		} else {
			if refOrderChildMin.Id == lastParentOrder.Id { // 取chiild 0 一定是左区， 与 lastParentOrder ID 相等就是左区
				//aa.UpdateLeftAreaIds(leftAreaId)
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.LeftAreaOrderIds = leftAreaId
				aa.Add()
			} else {
				//aa.UpdateRightAreaIds(leftAreaId)
				aa = model.NewAmountAward(incomeOrder.Id)
				aa.RightAreaOrderIds = leftAreaId
				aa.Add()
			}
		}
	} else {
		aa.UpdateLeftAreaIds(leftAreaId)

	}
}

/***
层奖计算
***/
// 计算,更新 order 层奖
func (a *Award) CalcAwardLayer() {

	// 收集层奖数据
	_recordLayerAward()

	// 么有计算的
	las := new(model.LayerAward).AllNotCalcLayerAward()
	if len(las) == 0 {
		return
	}

	for _, v := range las {
		//
		leftOrder := new(model.Orderr).ById(v.LeftAreaOrderId)
		rightOrder := new(model.Orderr).ById(v.RightAreaOrderId)
		selfOrder := new(model.Orderr).ById(v.IncomeOrderId)

		// 取小单级别，
		minOrderPrise := rightOrder.Price
		if leftOrder.Price < rightOrder.Price {
			minOrderPrise = leftOrder.Price
		}
		// 大不过自己单级别
		if minOrderPrise > selfOrder.Price {
			minOrderPrise = selfOrder.Price
		}
		// 更新层奖记录
		if v.Layer == 1 {
			v.Price = minOrderPrise * tool.LayerAwardRate
		} else {
			v.Price = minOrderPrise
		}
		v.Update()

		// 更新 order 层奖
		selfOrder.AwardLayer += v.Price
		selfOrder.UpdateAwardLayer()

		// TODO： 发送异步通知

	}

}

// 记录层奖
func _recordLayerAward() {

	todays := new(model.Today).All()

	recordLaLock := new(sync.Mutex)

	for _, v := range todays {
		recordLaLock.Lock()
		recordLayerAward(v)
		recordLaLock.Unlock()
		// v.Del() // 删除当前的新增单
	}

}

// 记录受益人的层碰数据
func recordLayerAward(todayOne *model.Today) {

	newOrder := new(model.Orderr).ById(todayOne.OrderId)
	// 受益orders
	orderBeneficiarys := make(map[int]*model.Orderr, 0)

	GetOrdersForParentId(newOrder, newOrder.ParentId, orderBeneficiarys)

	// 没有下级的 newOrder
	if len(orderBeneficiarys) == 0 {
		return
	}
	// 当前order layer 减去 受益order的layer, 就是受益order的第几层
	sortOrders := make([]int, len(orderBeneficiarys))
	i := 0
	for k, _ := range orderBeneficiarys {
		sortOrders[i] = k
		i++
	}

	sort.Ints(sortOrders)

	for iii, jjj := range sortOrders {
		kk := jjj

		//incomeOrder := new(model.Orderr) // 受益 order
		// kk 是 todayOne newOrder 的与受益 newOrder 的相对层
		incomeOrder := orderBeneficiarys[jjj] // 受益 order
		lastParentOrder := orderBeneficiarys[iii]

		refOrderChilds := incomeOrder.NextFloorOrdersByOrderId(incomeOrder.Id)

		if newOrder.Id == incomeOrder.Id {
			continue
		}

		// refOrderChilds 只有一个时,只可能添加层奖的左区 或 不添加
		if len(refOrderChilds) == 1 {
			if lastParentOrder == nil {
				childsExsit_1(*incomeOrder, *newOrder, *newOrder, kk)
			} else {
				childsExsit_1(*incomeOrder, *newOrder, *lastParentOrder, kk)
			}
		} else {
			// 双轨制左右区每层的第一个单和第二个单相碰，产生层碰
			if lastParentOrder == nil {
				childsExsit_2(*incomeOrder, *newOrder, *newOrder, kk)
			} else {
				childsExsit_2(*incomeOrder, *newOrder, *lastParentOrder, kk)
			}
		}

	}

}

// 下1层存在 1 个
func childsExsit_1(incomeOrder, newOrder, lastParentOrder model.Orderr, kk int) {
	la := new(model.LayerAward).ExistLeftAreaOrderIdLA(incomeOrder.Id, kk)

	// 存在相应层的层奖记录
	if la.Id > 0 {
		return
	}
	// 上 1 层
	if kk == 1 {
		model.NewLayerAward(incomeOrder.Id, newOrder.Id, newOrder.Id, kk).Add() // 不存在左区层奖记录  ， // 添加上一层的层碰左区单
	} else { // 上面 n 层
		model.NewLayerAward(incomeOrder.Id, newOrder.Id, lastParentOrder.Id, kk).Add() // 只有一个下级，并且 n 层的 左区记录不存在
	}
}

// 下1层存在两个
func childsExsit_2(incomeOrder, newOrder, lastParentOrder model.Orderr, kk int) {

	// kk  层的层奖
	la := new(model.LayerAward).ExistLeftAreaOrderIdLA(incomeOrder.Id, kk)

	if la.Id == 0 { // 两个下级，并不存在层奖记录，只有在系统延迟记录层奖的情况下
		if kk == 1 {
			model.NewLayerAward(incomeOrder.Id, newOrder.Id, newOrder.Id, kk).Add()
		} else {
			model.NewLayerAward(incomeOrder.Id, newOrder.Id, lastParentOrder.Id, kk).Add()
		}
		return
	}

	// right regional order
	if la.RightRegionalReferenceOrderId > 0 {
		return
	}

	// 上 1 层
	if kk == 1 {
		// 记录层碰的第二个单
		la.RightAreaOrderId = newOrder.Id
		la.RightRegionalReferenceOrderId = newOrder.Id
		la.UpdateRR()
	} else { // 上 n 层
		// 存在左区 n层的层奖记录，只会修改右区信息
		// n 层 左区右区不一致时才能完善层奖记录
		if la.LeftRegionalReferenceOrderId != lastParentOrder.Id {
			la.RightAreaOrderId = newOrder.Id
			la.RightRegionalReferenceOrderId = lastParentOrder.Id
			la.UpdateRR()
		}

	}

}

// 获取orders 推荐关系树
func GetOrdersForIntroducerId(layer int, orderOrigin *model.Orderr, introducerId int64, orders map[int]*model.Orderr) {

	// 根据一条当天的报单id 获取受益order
	introducerOrder := new(model.Orderr).ById(introducerId)

	if introducerOrder.Id == 0 {
		if orderOrigin.Id == 1 {
			introducerOrder = orderOrigin
		}
	}

	if introducerOrder.Id > 0 {
		orders[layer] = introducerOrder
		if introducerOrder.IntroducerId > 0 {
			GetOrdersForIntroducerId(layer+1, orderOrigin, introducerOrder.IntroducerId, orders)
		}
	}

}

// 获取orders 所有上层
// map int 是层数
func GetOrdersForParentId(orderOrigin *model.Orderr, orderParentId int64, orders map[int]*model.Orderr) {

	// 根据一条当天的报单id 获取受益order
	parentOrder := new(model.Orderr)
	parentOrder.ById(orderParentId)

	if parentOrder.Id == 0 {
		if orderOrigin.Id == 1 {
			parentOrder = orderOrigin
		}
	}

	if parentOrder.Id > 0 {
		orders[orderOrigin.Layer-parentOrder.Layer] = parentOrder
		if parentOrder.ParentId > 0 {
			GetOrdersForParentId(orderOrigin, parentOrder.ParentId, orders)
		}
	}
}
